package view;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;

public class SimulationTelevision extends RoundedPanel {

	private Map<Integer,GraphicNode> nodes = new TreeMap<Integer,GraphicNode>();
	private Vector<int[]> communications = new Vector<int[]>();
	private Vector<int[]> claims = new Vector<int[]>();
	private int squareSide;
	private int pointDim=6;
	private boolean firstTime=true;
	private boolean alreadyDrawed=false;
	
	
	
	public SimulationTelevision(){
		
		setSize(200,200);
		setBackground(Color.WHITE);
		setLayout(new GridBagLayout());		
		
	}
	
	/**
	 * call addNode(int, int, float, float, boolean) to add the node with the given information to the list nodes
	 * @param ID the univocal identification number
	 * @param id the id associated to the node
	 * @param xy the position of the node
	 * @param isClone if the given node is a clone
	 */
	public void addNode(int ID, int id, Point2D.Float xy, boolean isClone){
		addNode(ID, id, xy.x, xy.y, isClone);
	}
	
	/**
	 * add the node with the given information to the list nodes
	 * @param ID the univocal identification number
	 * @param id the id associated to the node
	 * @param xy the position of the node
	 * @param isClone if the given node is a clone
	 */
	public void addNode(int ID,int id, float x, float y, boolean isClone){
		nodes.put(ID,new GraphicNode(id,x,y,isClone));
	}
	
	/**
	 * delete all the information in the graphics. Will be called before start a new visualization.
	 */
	public void deathNodes(){
		nodes = new TreeMap<Integer,GraphicNode>();
		communications = new Vector<int[]>();
		claims = new Vector<int[]>();
		alreadyDrawed=false;
	}
	
	/**
	 * update the graphics. Will be called at the start of a new simulation.
	 */
	public void start(){
		update(getGraphics());
	}
	
	/**
	 * add a communication between nodes to the communication list and update the graphic 
	 * @param ID the id of the node that send the message
	 * @param id the id of the node that receive the message
	 */
	public void addCommunication(int ID, int id){
		int[] i = {ID,id};
		communications.add(i);
		update(getGraphics());
	}
	
	/**
	 * add a locationClaim between nodes to the communication list and update the graphic 
	 * @param ID the id of the node that send the message
	 * @param id the id of the node that receive the message
	 */
	public void addClaim(int ID, int id){
		int[] i = {ID,id};
		claims.add(i);
		update(getGraphics());
	}
	
	/**
	 * change the color to the death node
	 * @param ID the id of the node that don't have more energy
	 */
	public void endEnergy(int ID){
		for (int i=1; i<nodes.size(); i++){
			if (nodes.get(ID)!=null) nodes.get(ID).death();
		}
		alreadyDrawed=false;
		update(getGraphics());
	}
	
	
	public void paint(Graphics g) {
		// draw node
		if (nodes.size()>0 && !alreadyDrawed){ drawNodes(g); alreadyDrawed=true;}
		if (claims.size()>0) drawClaims(g);
		if (communications.size()>0) drawCommunications(g);
	}
	
	private void drawNodes(Graphics g){
		Dimension size = getSize();
		squareSide = Math.min(size.height, size.width);
		g.setColor(Color.WHITE);
		g.fillRect(0, 0, squareSide, squareSide);
		squareSide-=pointDim;
		GraphicNode n;
		for(Map.Entry<Integer, GraphicNode> entry : nodes.entrySet()) {
			n=entry.getValue();
			g.setColor(n.color);
			g.fillOval((int) ((squareSide-pointDim) * n.x), (int) ((squareSide-pointDim) * n.y), pointDim, pointDim);
		}
	}
	
	private void drawCommunications(Graphics g){
		g.setColor(Color.BLACK);
		GraphicNode start, end;
		for (int i=0; i<communications.size(); i++){
			start = nodes.get(communications.get(i)[0]);
			end = nodes.get(communications.get(i)[1]);
			if (start!=null || end!=null)
			{g.drawLine((int) ((squareSide-pointDim)*start.x) + pointDim/2, (int) ((squareSide-pointDim)*start.y) + pointDim/2,
					(int) ((squareSide-pointDim)*end.x) + pointDim/2, (int) ((squareSide-pointDim)*end.y) + pointDim/2);
			}
			else{
				System.out.print("errore com");
			}
		}
	}
	
	private void drawClaims(Graphics g){
		g.setColor(Color.GREEN);
		GraphicNode start, end;
		for (int i=0; i<claims.size(); i++){
			start = nodes.get(claims.get(i)[0]);
			end = nodes.get(claims.get(i)[1]);
			if (start!=null && end!=null)
			{g.drawLine((int) (squareSide*start.x) + pointDim/2, (int) (squareSide*start.y) + pointDim/2,
					(int) (squareSide*end.x) + pointDim/2, (int) (squareSide*end.y) + pointDim/2);
			}
			else{
				System.out.print("errore com");
			}
		}
		
	}
	
	
	
	private class GraphicNode{
		
		public int id;
		public float x;
		public float y;
		private Color color;
		public boolean isClone;
		
		public GraphicNode(int id, float x, float y, boolean isClone){
			this.id=id;
			this.x=x;
			this.y=y;
			this.isClone=isClone;
			if (isClone) color=Color.RED;
			else color=Color.CYAN;
		}
		
		public void death(){
			if (isClone) color=Color.BLACK;
			else color=Color.DARK_GRAY;
		}
		
	}
}
